<?php

/**
 * 
 * 回调基础类
 * @author widyhu
 *
 */
require_once "WxPay.Data.php";
require_once "WxPay.Api.php";

class WxPayNotify extends WxPayNotifyReply {

    /**
     * 
     * 回调入口
     * @param bool $needSign  是否需要签名输出
     */
    final public function Handle($needSign = true) {
        $msg = "OK";
        //当返回false的时候，表示notify中调用NotifyCallBack回调失败获取签名校验失败，此时直接回复失败
        $result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);
        if ($result == false) {
            $this->SetReturn_code("FAIL");
            $this->SetReturn_msg($msg);
            return $this->ReplyNotify(false);
        } else {
            //该分支在成功回调到NotifyCallBack方法，处理完成之后流程
            $this->SetReturn_code("SUCCESS");
            $this->SetReturn_msg("OK");
        }
        return $this->ReplyNotify($needSign);
    }

    /**
     * 
     * 回调方法入口，子类可重写该方法
     * 注意：
     * 1、微信回调超时时间为2s，建议用户使用异步处理流程，确认成功之后立刻回复微信服务器
     * 2、微信服务器在调用失败或者接到回包为非确认包的时候，会发起重试，需确保你的回调是可以重入
     * @param array $data 回调解释出的参数
     * @param string $msg 如果回调处理失败，可以将错误信息输出到该方法
     * @return true回调出来完成不需要继续回调，false回调处理未完成需要继续回调
     */
    public function NotifyProcess($data, &$msg) {
        //TODO 用户基础该类之后需要重写该方法，成功的时候返回true，失败返回false
        return true;
    }

    /**
     * 
     * notify回调方法，该方法中需要赋值需要输出的参数,不可重写
     * @param array $data
     * @return true回调出来完成不需要继续回调，false回调处理未完成需要继续回调
     */
    final public function NotifyCallBack($data) {
        $msg = "OK";
        $result = $this->NotifyProcess($data, $msg);

        if ($result == true) {
            $this->SetReturn_code("SUCCESS");
            $this->SetReturn_msg("OK");
        } else {
            $this->SetReturn_code("FAIL");
            $this->SetReturn_msg($msg);
        }
        return $result;
    }

    /**
     * 
     * 回复通知
     * @param bool $needSign 是否需要签名输出
     */
    final private function ReplyNotify($needSign = true) {
        //如果需要签名
        if ($needSign == true &&
                $this->GetReturn_code($return_code) == "SUCCESS") {
            $this->SetSign();
        }
        return WxpayApi::replyNotify($this->ToXml());
    }

    /**
     * 
     * @param type $openId
     * @param type $orderNo
     * @return type
     */
    public function unifiedorder($openId, $orderNo, $totalFee, $notify_url = "https://rpgminidev.gjgj.com/Pay/wxPayOrderCallBack", $body = "打赏红包") {
        //统一下单
        $input = new \WxPayUnifiedOrder();
        $input->SetBody($body);
        $input->SetOut_trade_no($orderNo);
        $input->SetTotal_fee($totalFee);
        $input->SetOpenid($openId);
        $input->SetNotify_url($notify_url);
        $input->SetTrade_type("JSAPI");
        $result = WxPayApi::unifiedOrder($input);
        return $result;
    }

    public function createPaySign($result) {
        $time = time();
        $tmp['appId'] = WxPayConfig::APPID;
        $tmp['nonceStr'] = $result['nonce_str'];
        $tmp['package'] = 'prepay_id=' . $result['prepay_id'];
        $tmp['signType'] = 'MD5';
        $tmp['timeStamp'] = "$time"; //时间戳
        $data = $tmp;
        $data['paySign'] = $this->sign($tmp); //签名,具体签名方案参见微信公众号支付帮助文档;
        return $data;
    }

    //签名 $data要先排好顺序
    public function sign($data) {
        $stringA = '';
        foreach ($data as $key => $value) {
            if (!$value)
                continue;
            if ($stringA)
                $stringA .= '&' . $key . "=" . $value;
            else
                $stringA = $key . "=" . $value;
        }
        $wx_key = WxPayConfig::KEY; //申请支付后有给予一个商户账号和密码，登陆后自己设置key
        $stringSignTemp = $stringA . '&key=' . $wx_key; //申请支付后有给予一个商户账号和密码，登陆后自己设置key    
        return strtoupper(md5($stringSignTemp));
    }

}
